#include "stdafx.h"

#include "boost/shared_ptr.hpp"
#include "boost/timer.hpp"

#include "OpenCV/cv.h"
#include "OpenCV/cxcore.h"
#include "OpenCV/highgui.h"

#include "ColorUtils/Color.h"
#include "ColorUtils/Image.h"
#include "ColorUtils/DataImage.h"
#include "ColorUtils/CheckersImage.h"

#include "MathUtils/Ray.h"

#include "RayTracer/FirstIntersectionResult.h"
#include "RayTracer/SecondIntersectionResult.h"
#include "RayTracer/Intersectable.h"
#include "RayTracer/Plain.h"
#include "RayTracer/FlatRectangle.h"
#include "RayTracer/FlatSphere.h"
#include "RayTracer/FlatCylinder.h"
#include "RayTracer/TexturedCylinder.h"
#include "RayTracer/FlatBox.h"
#include "RayTracer/Light.h"
#include "RayTracer/FlatDisc.h"
#include "RayTracer/Scene.h"
#include "RayTracer/GreedyWorld.h"
#include "RayTracer/PinholeCamera.h"
#include "RayTracer/ShadedIntersectable.h"
#include "RayTracer/PointLight.h"

int _tmain(int argc, _TCHAR* argv[])
{
	boost::shared_ptr<std::vector<Intersectable_ptr>> objects(new std::vector<Intersectable_ptr>());

	Scene_ptr scene(new Scene());
	
// 	objects->push_back(
// 		Intersectable_ptr(
// 		new ShadedIntersectable(
// 		Intersectable_ptr(
// 		new FlatCylinder(Ray(Point(0, 0, 20), Direction(0.2, 0.3, 0.5)), 4, 2, Color(0, 1, 0.1)))
// 		, scene, Color(0.5, 0.5, 0.5), 100, Color(0.1, 0.1, 0.1), Color(0.2, 0.2, 0.2), 0)));
// 
// 	objects->push_back(
// 		Intersectable_ptr(
// 		new ShadedIntersectable(
// 		Intersectable_ptr(
// 		new FlatBox(Point(-20, -20, 10), Point(-40,-20, 10), Point(-20, -40, 10), Point(-20, -20, 30), Color(0, 1, 0.1)))
// 		, scene, Color(0.5, 0.5, 0.5), 100, Color(0.1, 0.1, 0.1), Color(0.2, 0.2, 0.2), 0)));
// 
// 	objects->push_back(
// 		Intersectable_ptr(
// 		new ShadedIntersectable(
// 		Intersectable_ptr(
// 		new FlatDisc(Ray(Point(0, 0, 20), Direction(-0.3, -0.4,- 0.2)), 13, Color(0, 1, 0.1)))
// 		, scene, Color(0.5, 0.5, 0.5), 100, Color(0.1, 0.1, 0.1), Color(0.2, 0.2, 0.2), 0)));

// 	objects->push_back(
// 		Intersectable_ptr(
// 		new ShadedIntersectable(
// 		Intersectable_ptr(
// 		new FlatSphere(Point(0, 0, 15),  5, Color(0.5, 0.15, 0.2)))
// 		, scene, Color(0.5, 0.5, 0.5), 100, Color(0.1, 0.1, 0.1), Color(0.2, 0.2, 0.2), 0)));
// 
// 	objects->push_back(
// 		Intersectable_ptr(
// 		new ShadedIntersectable(
// 		Intersectable_ptr(
// 		new FlatRectangle(Point(0, 10, 15),  Point(0, -10, 15), Point(-20, 10, 15), Color(0.5, 0.15, 0.2)))
// 		, scene, Color(0.5, 0.5, 0.5), 100, Color(0.1, 0.1, 0.1), Color(0.2, 0.2, 0.2), 0)));

		
 	objects->push_back(
		Intersectable_ptr(
		new ShadedIntersectable(
		Intersectable_ptr(
		new TexturedCylinder(Ray(Point(0, 0, 0), Direction(0, 0, 1)), 100, 6, 
			boost::shared_ptr<Image>(new CheckersImage(0.01, Color(1, 1, 1), Color(0.1, 0.1, 0.1)))))
 		, scene, Color(0.5, 0.5, 0.5), 100, Color(0.1, 0.1, 0.1), Color(0.2, 0.2, 0.2), 0)));

	//ShadedIntersectable(Intersectable*, Scene*, const Color& specular, int shininess, const Color& ambient, const Color& emission, double reflectance);

	boost::shared_ptr<std::vector<Light_ptr>> lights(new std::vector<Light_ptr>);

	lights->push_back(Light_ptr(new PointLight(scene, Point(0, 0, 0), Point(0.7, 0.01, 0), Color(0.5, 0.5, 0.5))));
	lights->push_back(Light_ptr(new PointLight(scene, Point(30, 20, 5), Point(0.7, 0.01, 0), Color(1, 1, 1))));
	//lights->push_back(Light_ptr(new PointLight(scene, Point(0, 0, 40), Point(0.7, 0.01, 0), Color(1, 1, 1))));

	scene->IntersectionFinder = World_ptr(new GreedyWorld()); //background color
	scene->Lights = lights;
	scene->Objects = objects;
	scene->AmbientLight = Color(0, 0, 0);
	scene->IntersectionFinder->Init(scene);
	scene->BackGroundColor = Color(0.01, 0.01, 0.4);

	PinholeCamera cam(Ray(Point(0,0,0), Direction(0,0,1)), Point(1,0,0), 1.40, 1.40, 1.40, 1);
	cam.Init(scene->IntersectionFinder);

	IplImage* img(cvCreateImage(cvSize(1000, 1000), IPL_DEPTH_8U , 3));
	boost::timer time;
	time.restart();
	cam.Draw(img, 0);
	std::cout << "Finished... time elapsed:" << time.elapsed();

	cvSaveImage("C:\\out.bmp", img);
	cvNamedWindow("RayTracer", 1);
	cvShowImage("RayTracer", img);
	cvWaitKey();
	cvDestroyWindow("RayTracer");
	cvReleaseImage(&img);
	
	Sleep(5000);
}
